using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Practices.EnterpriseLibrary.Data;
using System.Xml;
using System.IO;
using System.Xml.XPath;
using Instedd.Labs.Forms.Library;
using System.Data;
using System.Collections.Specialized;
using System.Configuration;

namespace Instedd.Forms.Library.Tests
{
    /// <summary>
    /// Summary description for UnitTest1
    /// </summary>
    [TestClass]
    public class SurveyManagerFixture
    {
        static Database db;
        static Database readOnlyDb;

        [ClassInitialize()]
        public static void ClassInitialize(TestContext testContext)
        {
            db = DatabaseFactory.CreateDatabase("FormsDatabase");
            readOnlyDb = DatabaseFactory.CreateDatabase("FormsReadOnlyDatabase");

        }

        [TestMethod]
        public void CreateSurveyBasedOnStringXmlCreatesSurveyAsXPathDocument()
        {
            SurveyManager manager = new SurveyManager(db);
            
            XPathDocument document = manager.CreateSurvey(File.ReadAllText("survey.xml"));
            
            Assert.IsNotNull(document);
            Assert.AreEqual("comments value", document.CreateNavigator().SelectSingleNode("Survey/comments").InnerXml);
            Assert.AreEqual("AA12CC34", document.CreateNavigator().SelectSingleNode("Survey/id").InnerXml);
            Assert.AreEqual("Adrian", document.CreateNavigator().SelectSingleNode("Survey/enteredBy").InnerXml);
            Assert.AreEqual("AL", document.CreateNavigator().SelectSingleNode("Survey/state").InnerXml);
        }

        [TestMethod]
        public void BasicCRUDOperationExecutesSuccesfully()
        {
            SurveyManager manager = new SurveyManager(db);

            XPathDocument document = new XPathDocument("survey.xml");

            manager.Save(document.CreateNavigator().SelectSingleNode("Survey"));
            Assert.IsNotNull(manager.GetSurveyById("AA12CC34"));

            manager.Update(document.CreateNavigator().SelectSingleNode("Survey"), true);
            Assert.IsNotNull(manager.GetSurveyById("AA12CC34"));

            manager.DeleteSurvey("AA12CC34");
            Assert.IsNull(manager.GetSurveyById("AA12CC34"));
        }

        [TestMethod]
        public void CreateSurveyBasedOnDbReaderCreatesAndSetAllSurveyProperties()
        {
            SurveyManager manager = new SurveyManager(readOnlyDb);

            using (IDataReader reader = manager.GetSurveysAsDataReader())
            {
                reader.Read();
                
                Survey firstSurvey = manager.CreateSurvey(reader);
                
                Assert.IsNotNull(firstSurvey);
                Assert.AreEqual("Adrian", firstSurvey.EnteredBy);
                Assert.AreEqual("Tom", firstSurvey.FirstName);
                Assert.AreEqual(1, firstSurvey.TotalOccupants);
                Assert.AreEqual(12d, firstSurvey.Latitude);
                Assert.AreEqual(33d, firstSurvey.Longitude);

                Assert.AreEqual("csv01", firstSurvey.ID);
                Assert.AreEqual(new DateTime(2000, 1, 1, 0, 0 , 0), firstSurvey.EnteredOn);
                Assert.AreEqual("P", firstSurvey.LastName);
                Assert.AreEqual("40st", firstSurvey.Address.StreetAddress);
                Assert.AreEqual("Redmond", firstSurvey.Address.City);
                Assert.AreEqual("WA", firstSurvey.Address.State);
                Assert.AreEqual("1000", firstSurvey.Address.PostalCode);
                Assert.AreEqual("4444-5555", firstSurvey.Phone);
                Assert.AreEqual("tom@domain.com", firstSurvey.Email);
                Assert.AreEqual(2, firstSurvey.AttendedConcert);
                Assert.AreEqual(3, firstSurvey.AttendeeContact);
                Assert.AreEqual(4, firstSurvey.SymptomsPresent);
                Assert.AreEqual(new DateTime(2000, 2, 2, 0, 0 , 0), firstSurvey.TimeOfOnset);
                Assert.AreEqual(1, firstSurvey.Deceased);
                Assert.AreEqual(2, firstSurvey.Under9years);
                Assert.AreEqual(3, firstSurvey.Pregnant);
                Assert.AreEqual(4, firstSurvey.AllergicDoxy);
                Assert.AreEqual("comment description", firstSurvey.Comments);
                Assert.AreEqual(6, firstSurvey.ReceivedIvTreatment);
                Assert.AreEqual(8, firstSurvey.Recovered);
                Assert.AreEqual("follow up comment", firstSurvey.FollowUpComments);
                Assert.AreEqual(10, firstSurvey.CiproDistributed);
                Assert.AreEqual(11, firstSurvey.DoxyDistributed);
                Assert.AreEqual(new DateTime(2003, 5, 25, 0, 0 , 0), firstSurvey.FollowUpEnteredOn);
                Assert.AreEqual(22, firstSurvey.DoxyCiproAllergy);
            }
        }

        [TestMethod]
        public void WriteCsvFileWithHeaderWritesDbFieldNamesInTheFirstLane()
        {
            SurveyManager manager = new SurveyManager(readOnlyDb);

            string csvFileName = Path.GetTempFileName();

            using (StreamWriter writer = new StreamWriter(csvFileName))
            {
                manager.WriteAllSurveysUsingCsvFormat(writer, true);
            }

            Assert.IsTrue(File.Exists(csvFileName));

            string[] fileContent = File.ReadAllLines(csvFileName);
            Assert.AreEqual(4, fileContent.Length);
            Assert.IsTrue(fileContent[0].Contains(","));
            // A few db field column names are checked
            Assert.IsTrue(fileContent[0].Contains("comments"));
            Assert.IsTrue(fileContent[0].Contains("enteredBy"));
            Assert.IsTrue(fileContent[0].Contains("id"));
            Assert.IsTrue(fileContent[0].Contains("doxyDistributed"));
        }

        [TestMethod]
        public void WriteCsvFileWithoutHeaderWritesSurveysValues()
        {
            SurveyManager manager = new SurveyManager(readOnlyDb);

            string csvFileName = Path.GetTempFileName();

            using (StreamWriter writer = new StreamWriter(csvFileName))
            {
                manager.WriteAllSurveysUsingCsvFormat(writer, false);
            }

            Assert.IsTrue(File.Exists(csvFileName));

            string[] fileContent = File.ReadAllLines(csvFileName);
            Assert.AreEqual(3, fileContent.Length);
            // Check the first record:
            Assert.IsTrue(fileContent[0].Contains(","));
            Assert.IsTrue(fileContent[0].Contains("csv01"));
            Assert.IsTrue(fileContent[0].Contains("Adrian"));
            Assert.IsTrue(fileContent[0].Contains("Tom"));
            Assert.IsTrue(fileContent[0].Contains("01-01-2000 00:00"));

            // Check the second record:
            Assert.IsTrue(fileContent[1].Contains(","));
            Assert.IsTrue(fileContent[1].Contains("csv02"));
            Assert.IsTrue(fileContent[1].Contains("Victor"));
            Assert.IsTrue(fileContent[1].Contains("John"));
            Assert.IsTrue(fileContent[1].Contains("07-07-2001 00:00"));

            // Check the third record:
            Assert.IsTrue(fileContent[2].Contains(","));
            Assert.IsTrue(fileContent[2].Contains("csv03"));
        }

        [ExpectedException(typeof(InvalidFormVersionException))]
        [TestMethod]
        public void InvalidFormVersionThrowsWhenTheFormIsSaved()
        {
            NameValueCollection configuration = new NameValueCollection(ConfigurationManager.AppSettings);
            configuration["formVersion"] = "1.4";
            SurveyManager manager = new SurveyManager(db, new MockGeoCoder(), configuration);

            XPathDocument survey = manager.CreateSurvey(File.ReadAllText("survey.xml"));
            manager.Save(survey.CreateNavigator());
        }

        // Rename the test and make more assertions about the totals values.
        [TestMethod]
        public void Test01()
        {
            SurveyManager manager = new SurveyManager(db, new MockGeoCoder());

            AggregatedSurveyTotals totals = manager.CalculateSurveyTotals();

            Assert.IsNotNull(totals);
        }
    }
}
